using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Nsb.Classes;
using Yoshi.Classes;
using jQueryApi;

namespace YoshiFlowCheck.Classes
{
    [IgnoreNamespace]
    public class PathReader : Actor
    {
        private readonly Help _help;
        private readonly List<Dictionary> _stack = new List<Dictionary>();
        private readonly Dictionary _vars;

        public PathReader(Dictionary path, Dictionary vars, Help help)
        {
            _vars = vars ?? new Dictionary();
            _help = help ?? new Help(Element);
            Element = jQuery.FromHtml("<div class='Path'/>");
            GeneratePath(path);
        }

        private void GeneratePath(Dictionary<string, string> path)
        {
            _help.Reset();
            _stack.Add(path);
            string type = path["type"];

            if (_stack.Count > 1)
            {
                jQuery.FromHtml("<div class='BackBtn'/>")
                    .AppendTo(Element)
                    .Html(Constants.LeftMark)
                    .Click(PopPathEv)
                    ;
            }

            if (type != null)
                switch (type)
                {
                    case "tri-bar":
                        {
                            _help.Message = "Click on the colored bar to make a choice.";
                            List<Dictionary> items = (List<Dictionary>) (object) path["items"];
                            Debug.Assert(items.Count == 3, "items.Count == 3");
                            jQuery.FromHtml("<h3 class='Question'/>")
                                .AppendTo(Element)
                                .Html(path["title"])
                                ;
                            jQueryObject bar = jQuery.FromHtml("<div class='Bar'/>")
                                .AppendTo(Element)
                                ;
                            jQuery.FromHtml("<span class='Low'/>")
                                .AppendTo(bar)
                                .Html((string) items[0]["title"])
                                .Data("next", (Action) delegate { GenerateItems((Dictionary) items[0]["items"]); })
                                .Click(ClickItemEv)
                                ;
                            jQuery.FromHtml("<span class='Medium'/>")
                                .AppendTo(bar)
                                .Html((string) items[1]["title"])
                                .Data("next", (Action) delegate { GenerateItems((Dictionary) items[1]["items"]); })
                                .Click(ClickItemEv)
                                ;
                            jQuery.FromHtml("<span class='High'/>")
                                .AppendTo(bar)
                                .Html((string) items[2]["title"])
                                .Data("next", (Action) delegate { GenerateItems((Dictionary) items[2]["items"]); })
                                .Click(ClickItemEv)
                                ;
                        }
                        break;

                    case "multi-list":
                        {
                            _help.Message = "Click on a line to make a choice.";
                            List<Dictionary> items = (List<Dictionary>) (object) path["items"];
                            jQueryObject dl = jQuery.FromHtml("<dl/>")
                                .AppendTo(Element)
                                ;

                            if (path["class"] != null)
                                dl.AddClass(path["class"]);

                            jQuery.FromHtml("<dt class='Question'/>")
                                .AppendTo(dl)
                                .Html(path["title"])
                                ;

                            for (int i = 0; i < items.Count; i++)
                            {
                                jQueryObject dd = jQuery.FromHtml("<dd/>")
                                    .AppendTo(dl)
                                    .Html((string) items[i]["title"])
                                    .Click(ClickItemEv)
                                    ;

                                AddDataItem(dd, items, i);
                            }
                        }
                        break;
                }
        }

        private void AddDataItem(jQueryObject el, List<Dictionary> items, int idx)
        {
            //Inform.Debug("Adding click key={0}", key);
            el.Data("next", (Action) delegate { GenerateItems((Dictionary) items[idx]["items"]); });
        }

        private void GenerateItems(Dictionary<string, Dictionary> items)
        {
            if (Type.GetScriptType(items) == "string")
            {
                string[] par = ((string) (object) items).Split(":");

                switch (par[0])
                {
                    case "@page":
                        Element.Closest(".FlowPath").Remove();
                        Hider(false);
                        string page = AllPages.Page(par[1]) ?? par[1];
                        Master.GoPage(page);
                        break;

                    default:
                        Element.Closest(".FlowPath").Remove();
                        Hider(false);
                        Action fn = (Action) _vars[par[0]];
                        if (fn != null)
                            fn();
                        break;
                }
                return;
            }
            Element.Empty();
            if (jQuery.IsArray(items))
                GeneratePath(((List<Dictionary>) (object) items)[0]);
            else
                GeneratePath((Dictionary) (object) items);
        }

        private void ClickItemEv(jQueryEvent e)
        {
            Action fn = (Action) jQuery.FromElement(e.Target).GetDataValue("next");
            fn();
        }

        private void PopPathEv(jQueryEvent e)
        {
            Dictionary path = _stack[_stack.Count - 2];
            Script.Literal("{0}.length = {0}.length - 2", _stack);
            Element.Empty();
            GeneratePath(path);
        }
    }
}